const DEFAULT_PROVIDER_URL = process.env.IP_LOCATION_PROVIDER_URL || 'https://ip-api.com/json/';
const CACHE_TTL_MS = parseInt(process.env.IP_LOCATION_CACHE_TTL_MS || '43200000', 10); // 12小时缓存
const REQUEST_TIMEOUT_MS = parseInt(process.env.IP_LOCATION_REQUEST_TIMEOUT_MS || '5000', 10);
const LOCATION_REFRESH_INTERVAL_MS = parseInt(process.env.USER_LOCATION_REFRESH_INTERVAL_MS || '43200000', 10); // 12小时刷新

const cache = new Map();

const fetch = (...args) => import('node-fetch').then(({ default: fetchFn }) => fetchFn(...args));

const MUNICIPALITIES = new Set(['北京', '天津', '上海', '重庆']);
const AUTONOMOUS_REGIONS = new Map([
  ['新疆', '新疆自治区'],
  ['新疆维吾尔自治区', '新疆自治区'],
  ['宁夏', '宁夏自治区'],
  ['宁夏回族自治区', '宁夏自治区'],
  ['广西', '广西自治区'],
  ['广西壮族自治区', '广西自治区'],
  ['内蒙古', '内蒙古自治区'],
  ['内蒙古自治区', '内蒙古自治区'],
  ['西藏', '西藏自治区'],
  ['西藏自治区', '西藏自治区']
]);
const SPECIAL_REGIONS = new Map([
  ['香港', '香港特别行政区'],
  ['香港特别行政区', '香港特别行政区'],
  ['澳门', '澳门特别行政区'],
  ['澳门特别行政区', '澳门特别行政区']
]);

function getClientIp(req) {
  if (!req) return null;

  const xForwarded = req.headers['x-forwarded-for'];
  if (typeof xForwarded === 'string' && xForwarded.length > 0) {
    const forwardedIps = xForwarded.split(',').map(ip => ip.trim()).filter(Boolean);
    if (forwardedIps.length > 0) {
      return normalizeIp(forwardedIps[0]);
    }
  }

  const realIp = req.headers['x-real-ip'];
  if (typeof realIp === 'string' && realIp.length > 0) {
    return normalizeIp(realIp.trim());
  }

  if (req.socket?.remoteAddress) {
    return normalizeIp(req.socket.remoteAddress);
  }

  if (req.ip) {
    return normalizeIp(req.ip);
  }

  return null;
}

function normalizeIp(rawIp) {
  if (!rawIp) return null;
  // IPv6 地址可能以 ::ffff: 前缀包装 IPv4
  if (rawIp.startsWith('::ffff:')) {
    return rawIp.substring(7);
  }
  return rawIp;
}

function isPrivateIp(ip) {
  if (!ip) return true;
  if (ip === '127.0.0.1' || ip === '::1') return true;

  const privateRanges = [
    /^10\./,
    /^192\.168\./,
    /^172\.(1[6-9]|2\d|3[0-1])\./
  ];

  return privateRanges.some(regex => regex.test(ip));
}

function normalizeProvinceName(name) {
  if (!name) return null;
  const trimmed = name.trim();
  if (!trimmed) return null;

  if (SPECIAL_REGIONS.has(trimmed)) {
    return SPECIAL_REGIONS.get(trimmed);
  }

  if (AUTONOMOUS_REGIONS.has(trimmed)) {
    return AUTONOMOUS_REGIONS.get(trimmed);
  }

  const stripped = trimmed
    .replace(/省$/u, '')
    .replace(/市$/u, '')
    .replace(/特别行政区$/u, '')
    .replace(/壮族自治区$/u, '')
    .replace(/回族自治区$/u, '')
    .replace(/维吾尔自治区$/u, '')
    .replace(/自治区$/u, '');

  if (SPECIAL_REGIONS.has(stripped)) {
    return SPECIAL_REGIONS.get(stripped);
  }

  if (AUTONOMOUS_REGIONS.has(stripped)) {
    return AUTONOMOUS_REGIONS.get(stripped);
  }

  if (MUNICIPALITIES.has(stripped)) {
    return `${stripped}市`;
  }

  if (stripped === '台湾') {
    return '台湾省';
  }

  if (!stripped) {
    return null;
  }

  return `${stripped}省`;
}

function toProvinceKey(name) {
  const normalized = normalizeProvinceName(name);
  if (!normalized) return null;
  return normalized;
}

async function lookupIp(ip) {
  if (!ip || isPrivateIp(ip)) {
    return null;
  }

  const cachedEntry = cache.get(ip);
  if (cachedEntry && Date.now() - cachedEntry.timestamp < CACHE_TTL_MS) {
    return cachedEntry.data;
  }

  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
  try {
    const url = `${DEFAULT_PROVIDER_URL}${ip}?lang=zh-CN&fields=status,message,regionName,city`;
    const response = await fetch(url, { signal: controller.signal });

    if (!response.ok) {
      console.warn(`IP定位请求失败(${response.status})`, await safeBodyText(response));
      return null;
    }

    const payload = await response.json();
    if (payload.status !== 'success') {
      console.warn('IP定位返回失败', payload.message);
      return null;
    }

    const province = normalizeProvinceName(payload.regionName);
    const city = payload.city ? payload.city.trim() : null;

    const data = {
      ip,
      province,
      city,
      raw: payload
    };

    cache.set(ip, { data, timestamp: Date.now() });
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.warn(`IP定位请求超时(${ip})`);
    } else {
      console.error('IP定位请求异常', error.message);
    }
    return null;
  } finally {
    clearTimeout(timeout);
  }
}

async function safeBodyText(response) {
  try {
    return await response.text();
  } catch (error) {
    return '';
  }
}

async function resolveLocationFromRequest(req) {
  const ip = getClientIp(req);
  if (!ip) {
    return null;
  }

  const location = await lookupIp(ip);
  if (!location) {
    return {
      ip,
      province: null,
      city: null
    };
  }

  return location;
}

function shouldRefreshUserLocation(user, location) {
  if (!user || !location) {
    return false;
  }

  if (!location.province) {
    return false;
  }

  if (!user.last_known_province || !user.last_known_ip) {
    return true;
  }

  if (user.last_known_ip !== location.ip) {
    return true;
  }

  if (user.last_known_province !== location.province) {
    return true;
  }

  if (!user.location_updated_at) {
    return true;
  }

  const lastUpdated = new Date(user.location_updated_at).getTime();
  if (Number.isNaN(lastUpdated)) {
    return true;
  }

  return Date.now() - lastUpdated > LOCATION_REFRESH_INTERVAL_MS;
}

function mapRegionToProvinceKey(region) {
  if (!region) return null;
  const normalized = region.trim();
  if (!normalized) return null;
  if (normalized === '全国' || normalized === '全国总群') {
    return '全国';
  }
  return toProvinceKey(normalized);
}

module.exports = {
  getClientIp,
  resolveLocationFromRequest,
  shouldRefreshUserLocation,
  mapRegionToProvinceKey,
  toProvinceKey,
  normalizeProvinceName,
  lookupIp,
  CACHE_TTL_MS,
  LOCATION_REFRESH_INTERVAL_MS
};
